/*
 * multiHandlerCom.c
 *
 *  Created on: 2010-3-20
 *      Author: abc
 */

#include "chatRoom.h"
#include <gtk/gtk.h>
extern GtkListStore *list_store;
extern pchatRoom pcrMain;
char  *  multicast_addr= "224.0.1.1 ";
extern GtkTextBuffer *bufferup,*bufferdown;
GtkTextIter iter1;
extern pclientinfoFS clientlinkFS;
extern pclientinfoFC clientlinkFC;
extern GtkWidget* textup;
enum {
	ROOMNAME,
    MEMNUM,
    HOSTNAME,
    DISCRIPTION,
    ISNEEDPASSWD,
    ID,
    N_COLUMNS
};

int check(int id){
	int result = crisexisted(pcrMain, id);
	return result;
}

void * multiThread(void* p){

	  int   s;
	  struct   sockaddr_in   srv;
	  int multiPort = 8189;

	  pchatRoom pcr = (pchatRoom)p;

	  bzero(&srv,sizeof(srv));
	  srv.sin_family=AF_INET;
	  srv.sin_addr.s_addr=inet_addr(multicast_addr);
	  srv.sin_port=htons(multiPort);

	  s=socket(AF_INET,SOCK_DGRAM,0);
	  if(s <0)
	  {
	    perror( "Opening   socket ");
	    return   0;
	  }


	  int id=rand()%10000;
	  pcr->id=id;
	  if(strcmp(pcr->description,"")==0)
		  pcr->isNeedPasswd=0;
	  else
		  pcr->isNeedPasswd=1;

	  while(1)
	  {

	    if(sendto(s,pcr,sizeof(chatRoom),0,(struct   sockaddr*)&srv,sizeof(srv)) <0)
	    {
	      perror( "sendto ");
	      return   0;
	    }
	    else
	    {
	      fprintf(stdout, "send   to   group   %s   :  %s   %s\n ",multicast_addr,pcr->roomName,pcr->hostName);
	    }
	    sleep(5);
	  }
}
void update(){
	/*GtkTreeIter iter,tmpIter;
	gtk_list_store_move_after(list_store, &iter,NULL);
	int id;
	pchatRoom p;
	do{
	gtk_tree_model_get((struct GtkTreeModel*)list_store,&iter,ID,id,-1);
	p=getByID(pcrMain,id);
	if(p->count<=0){
		crdeletelist(pcrMain,id);
		tmpIter=iter;
		gtk_list_store_remove(list_store,tmpIter);
		break;
	}
	}
	while(gtk_tree_model_iter_next((struct GtkTreeModel*)list_store,&iter));
*/
}

void * multiThreadForC(void* p){
	  int   s,n;
	  struct   sockaddr_in   srv,cli;
	  int   cli_len=sizeof(cli);
	  struct   ip_mreq   mreq;
	  chatRoom cr;
	  int multiPort = 8189;
	  bzero(&srv,sizeof(srv));
	  srv.sin_family=AF_INET;
	  srv.sin_addr.s_addr=htonl(INADDR_ANY);
	  srv.sin_port=htons(multiPort);

	  if((s=socket(AF_INET,SOCK_DGRAM,0)) <0)
	  {
	    perror( "Opening   socket ");
	    return   0;
	  }

	  if(bind(s,(struct   sockaddr*)&srv,sizeof(srv)) <0)
	  {
	    perror( "bind ");
	    return   0;
	  }

	  mreq.imr_multiaddr.s_addr=inet_addr(multicast_addr);
	  mreq.imr_interface.s_addr=htonl(INADDR_ANY);

	  if(setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) <0)
	  {
	    perror( "setsockopt:   IP_ADD_MEMBERSHIP ");
	    return   0;
	  }

	  while(1)
	  {
	    if((n=recvfrom(s,&cr,sizeof(chatRoom),0,(struct   sockaddr*)&cli,&cli_len)) !=sizeof(chatRoom))
	    {
	      perror( "recvfrom ");
	      //return   0;
	    }
	    else
	    {
	    	char* str = cr.isNeedPasswd?"需要密码":"不要密码";
	        fprintf(stdout, "host chatroom   %s   : %s   %s \n ",inet_ntoa(cli.sin_addr),cr.roomName,str);
	        if(cr.exit==1){
	        	  /*  GtkTreeIter iter,tmpIter;
	        		gtk_list_store_move_after(list_store, &iter,NULL);
	        		int id;
	        		do{
	        		gtk_tree_model_get(list_store,&iter,ID,id,-1);
	        		if(id==cr.id){
	        			crdeletelist(pcrMain,id);
	        			tmpIter=iter;
	        			gtk_list_mode_remove(list_store,tmpIter);
	        		    break;
	        		}
	        		}
	        		while(gtk_tree_model_iter_next(list_store,&iter));*/
	        }
	        else if(!check(cr.id)){
	           pchatRoom newCr=(pchatRoom)malloc(sizeof(chatRoom));
	           bcopy(&cr,newCr,sizeof(chatRoom));
	           bcopy(&cli,&newCr->addr_in,sizeof(struct   sockaddr_in));
	           //newCr->addr_in=cli;
	           newCr->count=10;
	           crinsertend(pcrMain,newCr);
	           GtkTreeIter iter;

	           gtk_list_store_append (list_store, &iter);
	              gtk_list_store_set (list_store, &iter,
	            		      ROOMNAME,cr.roomName,
	            		      MEMNUM,cr.memberNum,
	            		      HOSTNAME,cr.hostName,
	            		      DISCRIPTION,cr.description,
	            		      ISNEEDPASSWD,str,
	            		      ID,cr.id,
	                          -1);
	        }
	        else{
	        	pchatRoom tmp = getByID(pcrMain,cr.id);
	        	tmp->count++;
	        }
	        update();
	    }
	  }
}


void* handleclient (void* client)
{
	pclientinfoFS clientNode = (pclientinfoFS)client;
	int nread;
	struct message a;
	char buf[MAXLEN],str[MAXLEN];
	time_t timep;
	//printf("2client sockfd:%d\n",clientNode->sockfd);

	while(1)
	{
	        //printf("正在recving…………\n");
		while((nread = recv(clientNode->sockfd,&a,sizeof(a),0))<0)
		//printf("recv %d bytes %s from %s",nread,a.msg,a.name);
		  ;
		printf("recv %d bytes %s from %s with flag %s\n",nread,a.msg,a.name,a.flag);
		if(nread == 0)
		{
			strcpy(a.flag,"sermsg");
			printf("客户端%s退出\n",clientNode->name);

			pclientinfoFS L;
			L = clientlinkFS;
			L=L->next;
			sprintf(buf,"客户端%s退出\n",clientNode->name);
			deletelist(clientlinkFS ,clientNode->name);
			while(L != NULL)
			{
				send(L->sockfd,buf,strlen(buf)+1,0);
				L = L->next;
			}
			continue;

		}
		else if (strcmp(a.flag,"all") == 0)
		{
			if (strcmp(a.msg,"") != 0)
			{
			  printf("%s\n",a.msg);
			  pclientinfoFS L;
				L = clientlinkFS;
				L=L->next;
				strcpy(a.name,clientNode->name);
				printf("%s %s\n",a.name,a.msg);

				while(L != NULL)
				{
				  printf("%s %s\n",a.name,a.msg);
					if(L->sockfd != clientNode->sockfd)
					   send(L->sockfd,&a,sizeof(struct message),0);
					L = L->next;
				}
				char buffer[MAXLEN];
				time (&timep);
				sprintf(buffer,"%s %s发给所有人:%s\n\n",ctime(&timep),a.name,a.msg);
				gdk_threads_enter();
				gtk_text_buffer_get_end_iter(bufferup,&iter1);
				gtk_text_buffer_insert(bufferup,&iter1,buffer,-1);
				gtk_text_buffer_get_end_iter(bufferup,&iter1);
				GtkTextMark * tmp = gtk_text_buffer_create_mark(bufferup,NULL,&iter1,FALSE);
							gtk_text_view_scroll_to_mark((GtkTextView*)textup,tmp,0.3,TRUE,0.2,0.1);
				gdk_threads_leave();
				printf("%s %s发给所有人:%s\n\n",ctime(&timep),a.name,a.msg);
			}
			continue;
		}
		else if(strcmp(a.flag,"view") == 0)
		{
			pclientinfoFS L;
			int i = 1;
			L = clientlinkFS;
			L=L->next;
			memset(buf,0,strlen(buf));
			while(L != NULL)
			{
				memset(str,0,strlen(str));
				sprintf(str,"%d$%s$%s$\n",i,L->name,inet_ntoa(L->addr_in.sin_addr));
				strcat(buf,str);
				//      send(clientNode.decr,str,strlen(str)+1,0);
				L = L->next;
				i++;
			}
			strcpy(a.name,clientNode->name);
			strcpy(a.msg,buf);

			send(clientNode->sockfd,&a,sizeof(struct message),0);
			continue;

		}
		else if(strcmp(a.flag,"login") == 0)
	                {
		               strcpy(clientNode->name,a.name);
		               insertend(clientlinkFS,clientNode);
		               //send(clientNode.decr,buf,strlen(buf)+1,0);
		               printf("%s join the room!\n",a.name);
		               char buffer[MAXLEN];
		               sprintf(buffer,"%s join the room!\n",a.name);
		               gdk_threads_enter();
		               gtk_text_buffer_get_end_iter(bufferup,&iter1);
		               gtk_text_buffer_insert(bufferup,&iter1,buffer,-1);
		               gtk_text_buffer_get_end_iter(bufferup,&iter1);
		               GtkTextMark * tmp = gtk_text_buffer_create_mark(bufferup,NULL,&iter1,FALSE);
		               			gtk_text_view_scroll_to_mark((GtkTextView*)textup,tmp,0.3,TRUE,0.2,0.1);
		               			gdk_threads_leave();
	                   continue;

	                }
		else if(strcmp(a.flag,"private") == 0)
		{
			pclientinfoFS L;
			L = clientlinkFS;
			L=L->next;
			//sprintf(buf,"%s:%s\n",clientNode.name,a.msg);
			//strcpy(a.name,clientNode->name);
			while(L != NULL)
			{
				if (strcmp(L->name,a.name) == 0)
				{
					//send(L->data.decr,buf,strlen(buf)+1,0);
					send(L->sockfd,&a,sizeof(struct message),0);
					break;
				}
				L = L->next;
			}
			continue;
		}

        }
}

void* handleaccept(void *serverfd)
{

	while(1)
	{
	        socklen_t client_len;
	        int sockfd = *(int*)serverfd;
	        pclientinfoFS clientNode = (pclientinfoFS)malloc(sizeof(clientinfoFS));
	        struct sockaddr_in client_addr;
	        printf("正在handleaccept…………\n");
		client_len =sizeof(struct sockaddr_in);
		if((clientNode->sockfd = accept(sockfd,(struct sockaddr *)&client_addr,&client_len)) == -1)
		{
			printf("接收连接失败\n");
		}
		else
		{
			printf("与%s:%d连接建立成功\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
			clientNode->addr_in = client_addr;
			pthread_create(&clientNode->pid,NULL,(void *)handleclient,(void *)clientNode);

			//printf("1client sockfd:%d\n",clientNode->sockfd);
		}
		sleep(1);
	}
}

void handlerecvmsg(int *sockfd)
{
	int connfd = *sockfd;
	int nread;

	char str[1024];
	struct message recvmsg;
	time_t timep;

	while(1)
	{

		while((nread = recv(connfd,&recvmsg,sizeof(struct message),0))!=sizeof(struct message))
			;

		if(nread == 0)
		{
			printf("与服务器断开了连接\n");
			close(connfd);
			exit(0);
		}
		else if (strcmp(recvmsg.flag,"all") == 0)
		{
			time (&timep);
			sprintf(str,"%s %s发给所有人:%s\n\n",ctime(&timep),recvmsg.name,recvmsg.msg);
			printf("%s%s发给所有人:%s\n\n",ctime(&timep),recvmsg.name,recvmsg.msg);
			gdk_threads_enter();
			gtk_text_buffer_get_end_iter(bufferup,&iter1);
			gtk_text_buffer_insert(bufferup,&iter1,str,-1);
			gtk_text_buffer_get_end_iter(bufferup,&iter1);
			GtkTextMark * tmp = gtk_text_buffer_create_mark(bufferup,NULL,&iter1,FALSE);
			gtk_text_view_scroll_to_mark((GtkTextView*)textup,tmp,0.3,TRUE,0.2,0.1);
			gdk_threads_leave();
		}
		else if (strcmp(recvmsg.flag,"sermsg") == 0)
		{
			time (&timep);
			printf("%s服务器发给所有人:%s\n\n",ctime(&timep),recvmsg.msg);
			continue;
		}
		else if (strcmp(recvmsg.flag,"view") == 0)
		{
			time (&timep);
			printf("%s当前在线客户端:\n%s\n\n",ctime(&timep),recvmsg.msg);
			continue;
		}
	}
}
